home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Programming / MuManual / C_Sources / MuFastZero.c < prev    next >
C/C++ Source or Header  |  1999-11-28  |  39KB  |  1,060 lines

  1. /*****************************************************************
  2.  ** MuFastZero                                                  **
  3.  **                                                             **
  4.  ** A MMU library compatible zeropage remapper                  **
  5.  ** Version 40.11 28.11.1999 © THOR-Software, by Thomas Richter **
  6.  *****************************************************************/
  7.  
  8. /// Includes
  9. #include <exec/types.h>
  10. #include <exec/memory.h>
  11. #include <exec/ports.h>
  12. #include <exec/execbase.h>
  13. #include <dos/dos.h>
  14. #include <mmu/mmubase.h>
  15. #include <mmu/context.h>
  16. #include <mmu/mmutags.h>
  17. #include <workbench/startup.h>
  18.  
  19. #include <proto/exec.h>
  20. #include <proto/mmu.h>
  21. #include <proto/dos.h>
  22. #include <proto/icon.h>
  23.  
  24. #include <string.h>
  25. ///
  26. /// Defines
  27. #define STRINGDATE "28.11.99"
  28. #define STRINGVERSION "40.11"
  29. #define CACHEFLAGS (MAPP_CACHEINHIBIT|MAPP_COPYBACK|MAPP_NONSERIALIZED|MAPP_IMPRECISE)
  30.  
  31. #define TEMPLATE "ON=FASTZERO/S,OFF=NOFASTZERO/S,FASTEXEC/S,FORCENATIVE/S,MOVESSP=FASTSSP/S,STACKSIZE/K/N"
  32.  
  33. #define OPT_ON  0
  34. #define OPT_OFF 1
  35. #define OPT_FASTEXEC 2
  36. #define OPT_FORCENATIVE 3
  37. #define OPT_FASTSSP 4
  38. #define OPT_STACKSIZE 5
  39. #define OPT_WINDOW 6
  40. #define OPT_COUNT 7
  41. ///
  42. /// Statics
  43. struct MMUBase *MMUBase;
  44. struct DosLibrary *DOSBase;
  45. struct ExecBase *SysBase;
  46. struct Library *IconBase;
  47.  
  48. void *_cw_to;
  49. void *_cw_from;
  50. ULONG _cw_size;
  51. ///
  52. /// Protos
  53. int __asm __saveds main(void);
  54. int BuildFastZero(LONG fastexec);
  55. int RemoveFastZero(void);
  56. ULONG ChipLowEnd(void);
  57. int KillFastZero(void);
  58. struct RDArgs *ReadTTArgs(struct WBStartup *msg,LONG args[],struct RDArgs **tmp);
  59. BOOL SetPages(struct MMUContext *ctx,ULONG props,ULONG lower,ULONG size,ULONG pagesize,ULONG dest);
  60. void CopyMMULess(void *to,void *from,ULONG size);
  61. ULONG __CopyWO();
  62. int MoveSSP(LONG size);
  63. void SuperStackSwap(UBYTE *newstack,ULONG size);
  64. ///
  65. /// Strukturen
  66. struct FastZeroPort {
  67.         struct MsgPort          frp_Port;
  68.         UWORD                   frp_cludgefill;
  69.         void                   *frp_Logical;            /* Logical position this is remapped to */
  70.         void                   *frp_Physical;           /* Physical location of the RAM used for remapping */
  71.         ULONG                   frp_Lower;              /* where remapping was started */
  72.         ULONG                   frp_Size;               /* size of the allocated memory */
  73.         struct Library         *frp_Base;               /* Keep the library open */
  74.         struct MemHeader       *frp_LowMemHeader;
  75.         ULONG                   frp_CacheFlags;         /* Keeps the caching mode for the remapping destination */
  76.         char                    frp_Name[32];           /* keeps the name of the port */
  77. };
  78.  
  79. /* This is the port build by MuMove4k */
  80.  
  81. struct MuMove4KPort {
  82.         struct MsgPort          mrp_Port;
  83.         UWORD                   mrp_cludgefill;
  84.         void                   *mrp_private;
  85.         struct MemHeader       *mrp_LowMemHeader;
  86.         ULONG                   mrp_UpperEnd;
  87. };
  88. ///
  89.  
  90. char version[]="$VER: MuFastZero " STRINGVERSION " (" STRINGDATE ") © THOR";
  91.  
  92. /// main
  93. int __asm __saveds main(void)
  94. {
  95. LONG args[OPT_COUNT];
  96. struct RDArgs *rd,*myrd;
  97. struct Process *proc;
  98. int rc=20;
  99. LONG err;
  100. struct WBStartup *msg;
  101. BPTR oldout;
  102. struct MsgPort *oldconsole;
  103. LONG stack;
  104.  
  105.  
  106.         SysBase=*((struct ExecBase **)(4L));
  107.  
  108.         memset(args,0,sizeof(LONG)*OPT_COUNT);
  109.         /* Wait for the workbench startup, if any */
  110.         proc=(struct Process *)FindTask(NULL);
  111.  
  112.         if (!(proc->pr_CLI)) {
  113.                 WaitPort(&(proc->pr_MsgPort));
  114.                 msg=(struct WBStartup *)GetMsg(&(proc->pr_MsgPort));
  115.         } else  msg=NULL;
  116.  
  117.         if (DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",37L)) {
  118.                 if (MMUBase=(struct MMUBase *)OpenLibrary("mmu.library",41L)) {
  119.  
  120.                         myrd=NULL;      /* reset the temporary ReadArgs */
  121.                         oldout=NULL;
  122.                         oldconsole=NULL;
  123.                         if (msg) {
  124.                                 oldout=SelectOutput(NULL);
  125.                                 oldconsole=SetConsoleTask(NULL);
  126.                                 rd=ReadTTArgs(msg,args,&myrd);
  127.                         } else  rd=ReadArgs(TEMPLATE,args,NULL);
  128.  
  129.                         if (rd) {
  130.                                 if (!GetMMUType()) {
  131.                                         Printf("MuFastZero requires a working MMU.\n");
  132.                                         err=10;
  133.                                 } else {
  134.                                         /* Argument parser worked, call main routine */
  135.                                         err=0;
  136.  
  137.                                         if (args[OPT_FORCENATIVE])
  138.                                                 err=KillFastZero();
  139.  
  140.                                         if (err<10 && ((args[OPT_ON]) || ((!args[OPT_OFF]) && (!args[OPT_FASTSSP]))))
  141.                                                         err=BuildFastZero(args[OPT_FASTEXEC]);
  142.  
  143.                                         if (err<10 && args[OPT_OFF])
  144.                                                 err=RemoveFastZero();
  145.  
  146.                                         if (err<10 && args[OPT_FASTSSP]) {
  147.                                                 if (args[OPT_STACKSIZE]) {
  148.                                                         stack=*(LONG *)args[OPT_STACKSIZE];
  149.                                                 } else  stack=0;
  150.                                                 err=MoveSSP(stack);
  151.                                         }
  152.                                 }
  153.  
  154.                                 FreeArgs(rd);
  155.                                 if (myrd) FreeDosObject(DOS_RDARGS,myrd);
  156.                                 if (msg)  Close(SelectOutput(NULL));
  157.                         } else  err=IoErr();
  158.  
  159.                         if (msg) {
  160.                                 SelectOutput(oldout);
  161.                                 SetConsoleTask(oldconsole);
  162.                         }
  163.  
  164.                         if (err<64) {
  165.                                 rc=err;
  166.                                 err=0;
  167.                         } else {
  168.                                 if (!msg) PrintFault(err,"MuFastZero failed");
  169.                                 rc=10;
  170.                         }
  171.                         SetIoErr(err);
  172.  
  173.                         CloseLibrary((struct Library *)MMUBase);
  174.                 } else if (!msg) PrintFault(ERROR_OBJECT_NOT_FOUND,"MuFastZero requires the mmu.library V41 or better");
  175.                 CloseLibrary((struct Library *)DOSBase);
  176.         }
  177.  
  178.         if (msg) {
  179.                 Forbid();
  180.                 ReplyMsg((struct Message *)msg);
  181.         }
  182.  
  183.         return rc;
  184. }
  185. ///
  186. /// ReadTTArgs
  187. struct RDArgs *ReadTTArgs(struct WBStartup *msg,LONG args[],struct RDArgs **tmp)
  188. {
  189. struct WBArg *wbarg;
  190. struct DiskObject *dop;
  191. char **tt;                      /* ToolTypes array */
  192. char *wbstr;                    /* Our self-made workbench argument string */
  193. char *here;
  194. BPTR oldlock;
  195. ULONG len;
  196. struct RDArgs *rd=NULL,*myrd=NULL;
  197. LONG err=0;
  198. BPTR newout;
  199.  
  200.         if (IconBase=OpenLibrary("icon.library",37L)) {
  201.                 if (wbarg=msg->sm_ArgList) {
  202.                         /* use a project icon if there is one... */
  203.                         if (msg->sm_NumArgs > 1) wbarg++;
  204.  
  205.                         /* go into the directory */
  206.                         oldlock=CurrentDir(wbarg->wa_Lock);
  207.  
  208.                         if (dop=GetDiskObject(wbarg->wa_Name)) {
  209.                                 if (tt=dop->do_ToolTypes) {
  210.                                         /* Read a special tool type for the output window */
  211.  
  212.                                         /* Calc the size of the argument string */
  213.  
  214.                                         len = 3;        /* reserve space for SPC,LF,NUL */
  215.                                         while (*tt) {
  216.                                                 len += strlen(*tt)+1;   /* string, plus space */
  217.                                                 tt++;
  218.                                         }
  219.  
  220.                                         if (wbstr=AllocVec(len,MEMF_PUBLIC)) {
  221.                                                 /* Now copy the arguments into this string, one by one
  222.                                                    and check whether the argument string is still valid. */
  223.  
  224.                                                 tt=dop->do_ToolTypes;
  225.                                                 here=wbstr;
  226.                                                 do{
  227.                                                         *here='\0';                     /* terminate string */
  228.                                                         /* Check whether this tool type is
  229.                                                            commented out. Just ignore it in this case */
  230.                                                         if (*tt) {
  231.                                                                 if (**tt=='(' || **tt==';')
  232.                                                                         continue;
  233.  
  234.                                                                 strcpy(here,*tt);      /* Add TT string */
  235.                                                         }
  236.                                                         len=strlen(here);
  237.                                                         here[len]='\n';
  238.                                                         here[len+1]='\0';               /* terminate string */
  239.  
  240.                                                         /* Now try to ReadArg' this string */
  241.  
  242.                                                         /* release old arguments left over from last loop */
  243.                                                         if (rd) FreeArgs(rd);
  244.                                                         if (myrd) FreeDosObject(DOS_RDARGS,myrd);
  245.                                                         rd=NULL;
  246.                                                         memset(args,0,sizeof(LONG)*OPT_COUNT);
  247.  
  248.                                                         if (myrd=AllocDosObject(DOS_RDARGS,NULL)) {
  249.                                                                 /* Allocate and setup the ReadArgs source */
  250.                                                                 myrd->RDA_Source.CS_Buffer=wbstr;
  251.                                                                 myrd->RDA_Source.CS_Length=strlen(wbstr);
  252.  
  253.                                                                 if (rd=ReadArgs(TEMPLATE ",WINDOW/K",args,myrd)) {
  254.                                                                         /* Is this still valid? */
  255.                                                                         here[len]=' ';
  256.                                                                         here+=len+1;
  257.                                                                         /* if so, accept this argument and go on */
  258.                                                                 } else {
  259.                                                                         err=IoErr();
  260.                                                                         if (err==ERROR_NO_FREE_STORE) break;
  261.                                                                         else    err=0;  /* Ignore unknown or invalid arguments silently */
  262.                                                                 }
  263.                                                         } else {
  264.                                                                 err=ERROR_NO_FREE_STORE;
  265.                                                                 break;
  266.                                                         }
  267.                                                 }while(*tt++);
  268.  
  269.                                                 FreeVec(wbstr);
  270.                                         } else err=ERROR_NO_FREE_STORE;
  271.                                 } else err=ERROR_REQUIRED_ARG_MISSING; /* Huh, how should this happen ? */
  272.                                 FreeDiskObject(dop);
  273.                         } else err=IoErr();
  274.                         CurrentDir(oldlock);
  275.                 } else err=ERROR_REQUIRED_ARG_MISSING; /* This should not happen either */
  276.                 CloseLibrary(IconBase);
  277.         } else err=ERROR_OBJECT_NOT_FOUND;    /* This should not happen */
  278.  
  279.         /* Open an output stream */
  280.  
  281.         if (err==0) {
  282.                 if (newout=Open((args[OPT_WINDOW])?((char *)args[OPT_WINDOW]):("NIL:"),MODE_NEWFILE)) {
  283.                         SelectOutput(newout);
  284.                         /* Hack in the output console. Well, well... */
  285.                         SetConsoleTask(((struct FileHandle *)(BADDR(newout)))->fh_Type);
  286.                 } else err=IoErr();
  287.         }
  288.  
  289.         if (err) {
  290.                 if (rd)   FreeArgs(rd);
  291.                 if (myrd) FreeDosObject(DOS_RDARGS,myrd);
  292.                 SetIoErr(err);
  293.                 rd=NULL;
  294.                 myrd=NULL;
  295.         }
  296.  
  297.         *tmp=myrd;
  298.         return rd;
  299. }
  300. ///
  301. /// SetPages
  302. BOOL SetPages(struct MMUContext *ctx,ULONG props,ULONG lower,ULONG size,ULONG pagesize,ULONG dest)
  303. {
  304. ULONG pages,i;
  305. ULONG base;
  306.  
  307.         pages=size/pagesize;
  308.         base=0;
  309.         for(i=0;i<pages;i++) {
  310.                 if (!SetPageProperties(ctx,props,~0L,lower+base,MAPTAG_DESTINATION,dest+base,TAG_DONE))
  311.                         return FALSE;
  312.                 base+=pagesize;
  313.         }
  314.  
  315.         return TRUE;
  316. }
  317. ///
  318. /// BuildFastZero
  319. int BuildFastZero(LONG fastexec)
  320. {
  321. void *mem=NULL,*pmem=NULL;
  322. ULONG pagesize,size,psize,align;
  323. ULONG lower;
  324. struct FastZeroPort *port;
  325. struct MuMove4KPort *mport;
  326. struct MMUContext *ctx,*sctx;   /* default context, supervisorcontext */
  327. struct MinList *ctxl,*sctxl;    /* Copies of the mappings currently active */
  328. int err=ERROR_NO_FREE_STORE;
  329. ULONG props,cacheflags;
  330. BOOL retry;
  331.  
  332.  
  333.         Forbid();                               /* Shut up PatchWork */
  334.  
  335.         /* If this is already installed, warn and return. */
  336.  
  337.         if (FindPort("« MuFastZero »")) {
  338.                 Permit();
  339.                 Printf("MuFastZero already running.\n");
  340.                 return 5;
  341.         }
  342.  
  343.         Permit();
  344.  
  345.         ctx=DefaultContext();   /* get the default context */
  346.         sctx=SuperContext(ctx); /* get the supervisor context for this one */
  347.  
  348.         /* Read the size */
  349.         pagesize=GetPageSize(ctx);
  350.  
  351.         if (GetPageSize(sctx)!=pagesize) {
  352.                 Printf("Supervisor and user page size are different,\n"
  353.                        "MuFastZero can't be installed.\n");
  354.                 return 10;
  355.         }
  356.  
  357.         size=pagesize;
  358.         if (size>ChipLowEnd()) {
  359.                 size=0;
  360.         }
  361.         align=RemapSize(ctx);
  362.  
  363.         if (fastexec) {
  364.                 Forbid();
  365.                 mport=(struct MuMove4KPort *)FindPort("« MuMove4K »");
  366.                 if (mport) {
  367.                         size=mport->mrp_UpperEnd;
  368.                 }
  369.                 Permit();
  370.                 if (mport==NULL) {
  371.                         Printf("MuMove4K is not installed, can't remap ExecBase.\n");
  372.                         return 10;
  373.                 }
  374.         } else mport=NULL;
  375.  
  376.         if (size==0) {
  377.                 Printf("The MMU page size is too large for MuFastZero.\n");
  378.                 return 10;
  379.         }
  380.  
  381.         port=AllocMem(sizeof(struct FastZeroPort),MEMF_CLEAR|MEMF_PUBLIC);
  382.         if (port) {
  383.  
  384.          /* Lock the context, make sure nobody is messing with the memory */
  385.          LockContextList();      /* We've to lock the list first, we want to lock more than one */
  386.          LockMMUContext(ctx);
  387.          LockMMUContext(sctx);
  388.          err=0;
  389.  
  390.          /* Read the properties of the zeropage. If this is either invalid
  391.             or already remapped, don't touch. */
  392.  
  393.          lower=0;
  394.  
  395.          do {
  396.  
  397.                 retry=FALSE;
  398.                 props=GetPageProperties(ctx,lower,TAG_DONE);
  399.                 props|=GetPageProperties(sctx,lower,TAG_DONE);
  400.  
  401.                 if ((props & MAPP_INVALID) || (props & MAPP_SWAPPED) ||
  402.                     (props & MAPP_SUPERVISORONLY)) {
  403.  
  404.                         if (fastexec && (size>pagesize)) {
  405.                                 size-=pagesize;
  406.                                 lower+=pagesize;
  407.                                 retry=TRUE;
  408.                         } else {
  409.                                 Printf("The zero page is invalidated and can't be remapped.\n");
  410.                                 err=10;
  411.                         }
  412.                 }
  413.          } while(retry);
  414.  
  415.          if ((props & MAPP_REMAPPED) && (err==0)) {
  416.                 Printf("The zero page is already remapped.\n"
  417.                        "In case you want to disable remapping, or want to use the\n"
  418.                        "FASTEXEC option, specify FORCENATIVE to override the\n"
  419.                        "remapping.\n");
  420.                 err=10;
  421.          }
  422.  
  423.          if (err==0L) {
  424.  
  425.           /* We request FAST here, explicitly. Taking chip memory for the
  426.              image doesn't make sense, this isn't fast either... */
  427.  
  428.           mem=AllocAligned(size+lower,MEMF_PUBLIC|MEMF_FAST|MEMF_CLEAR,align);
  429.           if (mem) {
  430.            psize=size+lower;
  431.            pmem=mem;
  432.            PhysicalLocation(ctx,&pmem,&psize);
  433.            if (psize!=size+lower) {
  434.                 Printf("The allocated memory is fragmentated, unsupported by MuFastZero.\n");
  435.                 err=10;
  436.            }
  437.           } else err=ERROR_NO_FREE_STORE;
  438.          }
  439.  
  440.          if (err==0L) {
  441.  
  442.             cacheflags=GetProperties(ctx,(ULONG)mem,TAG_DONE) & CACHEFLAGS;
  443.  
  444.             /* Make a copy of the software levels to be able to restore
  445.                them later in case of an error. */
  446.  
  447.             if (ctxl=GetMapping(ctx)) {
  448.              if (sctxl=GetMapping(sctx)) {
  449.  
  450.               /* Modify both contexts such that the zeropage is SINGLE.
  451.                  This operation is very costy, but it doesn't matter
  452.                  except for speed penalties if this is not un-done */
  453.  
  454.               err=ERROR_NO_FREE_STORE;
  455.               props=MAPP_SINGLEPAGE;
  456.  
  457.               if (SetProperties(ctx,props,props,lower,size,TAG_DONE)) {
  458.                if (SetProperties(sctx,props,props,lower,size,TAG_DONE)) {
  459.                 if (RebuildTrees(ctx,sctx,NULL)) {
  460.  
  461.                   /* Copy the zeropage over */
  462.                   Disable();
  463.  
  464.                   /* Fill in SysBase at location 4 */
  465.                   ((ULONG *)mem)[1]=(ULONG)SysBase;
  466.                   memcpy((char *)mem+lower,(char *)lower,(size_t)size);
  467.  
  468.                   /* The new property flags, or in the cache flags */
  469.                   props=MAPP_REMAPPED|MAPP_SINGLEPAGE|cacheflags;
  470.                   CacheClearU();
  471.  
  472.                   /* Map in the properties immediately. This should always work,
  473.                      except the parameters are invalid - which they aren't.
  474.                      This extra step is required because all other calls might
  475.                      break the Disable() above. */
  476.                   if (SetPages(ctx,props,lower,size,pagesize,(ULONG)pmem+lower)) {
  477.                    if (SetPages(sctx,props,lower,size,pagesize,(ULONG)pmem+lower)) {
  478.  
  479.                     /* Tell the contexts to relocate the zero page even in case MuForce
  480.                        is installed later, i.e. the software emulation should read
  481.                        the data from the relocated position, not from the original. */
  482.  
  483.                     SetMMUContextData(ctx,MCXTAG_ZEROBASE,pmem,TAG_DONE);
  484.                     SetMMUContextData(sctx,MCXTAG_ZEROBASE,pmem,TAG_DONE);
  485.  
  486.                     /* Now make the modifications in the abstraction level. */
  487.                     if (SetProperties(ctx,props,~0L,lower,size,MAPTAG_DESTINATION,(ULONG)pmem+lower,TAG_DONE)) {
  488.                      if (SetProperties(sctx,props,~0L,lower,size,MAPTAG_DESTINATION,(ULONG)pmem+lower,TAG_DONE)) {
  489.  
  490.                         /* The modifications in the hardware level are actually already done.
  491.                            Calling RebuildTree isn't stricly required here, but we do it
  492.                            anyways to clear the dirty flags. This might or might not fail,
  493.                            but the resulting MMU trees are always what we want. In
  494.                            case it fails, the dirty flags are set. So what... */
  495.  
  496.                         /* The RebuildTree's are below... */
  497.  
  498.                         /* Everything worked fine so far.... */
  499.                         port->frp_Port.mp_Node.ln_Type=NT_MSGPORT;
  500.                         port->frp_Port.mp_Node.ln_Name=port->frp_Name;
  501.                         strcpy(port->frp_Name,"« MuFastZero »");
  502.                         port->frp_Port.mp_Flags=PA_IGNORE;
  503.                         NewList(&(port->frp_Port.mp_MsgList));
  504.  
  505.                         port->frp_Physical=pmem;
  506.                         port->frp_Logical=mem;
  507.                         port->frp_Size=size;
  508.                         port->frp_Lower=lower;
  509.                         port->frp_CacheFlags=cacheflags;
  510.                         if (mport) {
  511.                                 port->frp_LowMemHeader=mport->mrp_LowMemHeader;
  512.                                 port->frp_LowMemHeader->mh_Attributes=0x0000;   /* remove the chip attribute */
  513.                         }
  514.  
  515.                         port->frp_Base=OpenLibrary("mmu.library",0L);
  516.                         AddPort(&(port->frp_Port));
  517.  
  518.  
  519.                         /* We're done here. Fine. */
  520.                         err=0;
  521.                         mem=NULL;
  522.                         port=NULL;
  523.  
  524.                      }
  525.                     }
  526.  
  527.                    /* We can't set the software level. Urgh. At least, we can
  528.                       restore it how it looked like before. */
  529.                    }
  530.                   }
  531.  
  532.                   /* We try to restore the hardware tables now. */
  533.                   if (err) {
  534.                         props=MAPP_CACHEINHIBIT|MAPP_SINGLEPAGE;
  535.  
  536.                         if ((!SetPageProperties(ctx,props,~0L,0L,TAG_DONE)) ||
  537.                             (!SetPageProperties(sctx,props,~0L,0L,TAG_DONE))) {
  538.                                 /* We can't restore the hardware tables either! */
  539.                                 Alert(0xbe000101);
  540.                                 /* Sorry, go guru. We can't do much more here... */
  541.                         }
  542.                   }
  543.                   Enable();
  544.                 }
  545.                }
  546.               }
  547.  
  548.               /* We can't build the software level. In the one way or the other,
  549.                  just restore the previous software abstraction level. */
  550.  
  551.               if (err) {
  552.                 SetPropertyList(ctx,ctxl);
  553.                 SetPropertyList(sctx,sctxl);
  554.               }
  555.  
  556.               /* The software level is now restored. The
  557.                  hardware level has been restored above.
  558.                  Now call RebuildTree() to clear the dirty
  559.                  flags.
  560.                  If this fails, tough luck. Both levels are
  561.                  actually fine, except for the busy flags. */
  562.  
  563.               RebuildTrees(ctx,sctx,NULL);
  564.  
  565.               ReleaseMapping(sctx,sctxl);
  566.              }
  567.              ReleaseMapping(ctx,ctxl);
  568.             }
  569.          }
  570.  
  571.            /* Release the locks */
  572.          UnlockMMUContext(sctx);
  573.          UnlockMMUContext(ctx);
  574.          UnlockContextList();
  575.  
  576.          if (mem) FreeMem(mem,size+lower);
  577.          if (port) FreeMem(port,sizeof(struct FastZeroPort));
  578.         }
  579.  
  580.         return err;
  581. }
  582. ///
  583. /// RemoveFastZero
  584. int RemoveFastZero(void)
  585. {
  586. struct MMUContext *ctx,*sctx;
  587. struct MinList *ctxl,*sctxl;
  588. struct FastZeroPort *port;
  589. ULONG size,pagesize,lower;
  590. void *mem,*pmem;
  591. ULONG props,cacheflags;
  592. int err;
  593.  
  594.         Forbid();                               /* Shut up PatchWork */
  595.  
  596.         /* If this is not installed, warn and return. */
  597.  
  598.         port=(struct FastZeroPort *)FindPort("« MuFastZero »");
  599.  
  600.         if (port==NULL) {
  601.                 Permit();
  602.                 Printf("MuFastZero not installed.\n");
  603.                 return 5;
  604.         }
  605.         /* Remove it, to ensure nobody else tries to remove it */
  606.         RemPort(&(port->frp_Port));
  607.         Permit();
  608.  
  609.         ctx=DefaultContext();   /* get the default context */
  610.         sctx=SuperContext(ctx); /* get the supervisor context for this one */
  611.  
  612.         pagesize=GetPageSize(ctx);
  613.         if (GetPageSize(sctx)!=pagesize) {
  614.                 Printf("Supervisor and user page size are different,\n"
  615.                        "MuFastZero can't be removed.\n");
  616.                 return 10;
  617.         }
  618.  
  619.         LockContextList();      /* We've to lock the list first, we want to lock more than one */
  620.         LockMMUContext(ctx);
  621.         LockMMUContext(sctx);
  622.  
  623.         err=ERROR_NO_FREE_STORE;
  624.  
  625.         /* Make a copy of the mapping like it is now */
  626.         if (ctxl=GetMapping(ctx)) {
  627.          if (sctxl=GetMapping(sctx)) {
  628.  
  629.           /* Read the properties of the zeropage. If this is either invalid
  630.              or already remapped, don't touch. */
  631.  
  632.           lower=port->frp_Lower;
  633.           props=GetPageProperties(ctx,lower,TAG_DONE);
  634.           props|=GetPageProperties(sctx,lower,TAG_DONE);
  635.           err=0;
  636.  
  637.           if ((props & MAPP_INVALID) || (props & MAPP_SWAPPED) ||
  638.               (props & MAPP_SUPERVISORONLY)) {
  639.                 Printf("The zero page is now invalidated and can't be restored for that reason.\n");
  640.                 err=10;
  641.           }
  642.  
  643.           if ((err==0) && ((props & MAPP_REMAPPED)==0)) {
  644.                 Printf("The zero page is no longer remapped to FastMem.\n");
  645.                 err=10;
  646.           }
  647.  
  648.           /* If everything is fine so far, start removing things */
  649.           if (err==0) {
  650.            size=port->frp_Size;
  651.            pmem=port->frp_Physical;
  652.            mem=port->frp_Logical;
  653.            lower=port->frp_Lower;
  654.            cacheflags=port->frp_CacheFlags;
  655.            Disable();
  656.  
  657.            err=ERROR_NO_FREE_STORE;
  658.            props=MAPP_CACHEINHIBIT|MAPP_SINGLEPAGE;       /* This is the only flag for chip memory */
  659.  
  660.            /* Now copy the data back to the zeropage */
  661.            CopyMMULess((char *)lower,(char *)pmem+lower,size);
  662.  
  663.            /* First, try to modify the hardware tables. */
  664.            if (SetPages(ctx,props,lower,size,pagesize,lower)) {
  665.             if (SetPages(sctx,props,lower,size,pagesize,lower)) {
  666.  
  667.              /* read the data again from the real stuff */
  668.              SetMMUContextData(ctx,MCXTAG_ZEROBASE,0L,TAG_DONE);
  669.              SetMMUContextData(sctx,MCXTAG_ZEROBASE,0L,TAG_DONE);
  670.  
  671.              /* Restore the software level,singlepage is no longer required */
  672.  
  673.              props=MAPP_CACHEINHIBIT;
  674.              if (SetProperties(ctx,props,~0L,lower,size,TAG_DONE)) {
  675.               if (SetProperties(sctx,props,~0L,lower,size,TAG_DONE)) {
  676.  
  677.                         if (port->frp_LowMemHeader) {
  678.                                 /* No, neither public nor anything else */
  679.                                 port->frp_LowMemHeader->mh_Attributes=MEMF_CHIP;
  680.                         }
  681.  
  682.                         FreeMem(mem,size+lower);
  683.                         if (port->frp_Base)
  684.                                 CloseLibrary(port->frp_Base);
  685.  
  686.                         FreeMem(port,sizeof(struct FastZeroPort));
  687.                         err=0;
  688.               }
  689.              }
  690.  
  691.               /* We can't setup the software level. Urgh. At least,
  692.                  we should try to set things back how they used to be. */
  693.             }
  694.            }
  695.  
  696.  
  697.            /* We try to restore the hardware tables now. */
  698.            if (err) {
  699.                 props=MAPP_REMAPPED|MAPP_SINGLEPAGE|cacheflags;
  700.                 SetMMUContextData(ctx,MCXTAG_ZEROBASE,(ULONG)pmem+lower,TAG_DONE);
  701.                 SetMMUContextData(sctx,MCXTAG_ZEROBASE,(ULONG)pmem+lower,TAG_DONE);
  702.  
  703.                 if ((!SetPages(ctx,props,lower,size,pagesize,(ULONG)pmem+lower)) ||
  704.                     (!SetPages(sctx,props,lower,size,pagesize,(ULONG)pmem+lower))) {
  705.                         /* We can't restore the hardware tables either! */
  706.                         Alert(0xbe000101);
  707.                         /* Sorry, go guru. We can't do much more here... */
  708.                 }
  709.            }
  710.            Enable();
  711.  
  712.            if (err) {
  713.                 SetPropertyList(ctx,ctxl);
  714.                 SetPropertyList(sctx,sctxl);
  715.                 /* More luck next time */
  716.                 AddPort(&(port->frp_Port));
  717.            }
  718.  
  719.              /* The software level is now restored. The
  720.                 hardware level has been restored above.
  721.                 Now call RebuildTree() to clear the dirty
  722.                 flags.
  723.                 If this fails, tough luck. Both levels are
  724.                 actually fine, except for the busy flags. */
  725.  
  726.            RebuildTrees(ctx,sctx,NULL);
  727.           }
  728.           ReleaseMapping(sctx,sctxl);
  729.          }
  730.          ReleaseMapping(ctx,ctxl);
  731.         }
  732.  
  733.  
  734.         UnlockMMUContext(sctx);
  735.         UnlockMMUContext(ctx);
  736.         UnlockContextList();      /* We've to lock the list first, we want to lock more than one */
  737.  
  738.         if (err) {
  739.                 /* Uhoh, things didn't work here... */
  740.                 Printf("Can't remove the FastZero node, sorry.\n");
  741.         }
  742.  
  743.         return err;
  744. }
  745. ///
  746. /// KillFastZero
  747. int KillFastZero(void)
  748. {
  749. struct FastZeroPort *port;
  750. struct MMUContext *ctx,*sctx;   /* default context, supervisorcontext */
  751. struct MinList *ctxl,*sctxl;    /* Copies of the mappings currently active */
  752. ULONG pagesize;
  753. ULONG lower,size,props;
  754. ULONG userpos,superpos,base;
  755. int err;
  756. BOOL retry;
  757.  
  758.  
  759.         Forbid();                               /* Shut up PatchWork */
  760.  
  761.         /* If MuFastZero is installed, remove it the easy way */
  762.  
  763.         port=(struct FastZeroPort *)FindPort("« MuFastZero »");
  764.  
  765.         if (port) {
  766.                 Permit();
  767.                 return RemoveFastZero();
  768.         }
  769.  
  770.         Permit();
  771.  
  772.         ctx=DefaultContext();   /* get the default context */
  773.         sctx=SuperContext(ctx); /* get the supervisor context for this one */
  774.  
  775.         /* Read the size */
  776.         pagesize=GetPageSize(ctx);
  777.  
  778.         if (GetPageSize(sctx)!=pagesize) {
  779.                 Printf("Supervisor and user page size are different,\n"
  780.                        "MuFastZero failed.\n");
  781.                 return 10;
  782.         }
  783.  
  784.         /* Lock the context, make sure nobody is messing with the memory */
  785.         LockContextList();      /* We've to lock the list first, we want to lock more than one */
  786.         LockMMUContext(ctx);
  787.         LockMMUContext(sctx);
  788.         err=0;
  789.  
  790.         /* Read the properties of the zeropage. If this is either invalid
  791.            or not remapped, don't touch. */
  792.  
  793.         lower=0;
  794.         size=0;
  795.         base=0;
  796.  
  797.         do {
  798.  
  799.                 retry=FALSE;
  800.                 userpos=superpos=0;
  801.                 props=GetPageProperties(ctx,lower+size,
  802.                                         MAPTAG_DESTINATION,&userpos,
  803.                                         TAG_DONE);
  804.                 props|=GetPageProperties(sctx,lower+size,
  805.                                          MAPTAG_DESTINATION,&superpos,
  806.                                          TAG_DONE);
  807.  
  808.                 if ((props & MAPP_INVALID) || (props & MAPP_SWAPPED) ||
  809.                     (props & MAPP_SUPERVISORONLY)) {
  810.  
  811.                         lower += pagesize;
  812.                         retry = TRUE;
  813.  
  814.                 } else if (props & MAPP_REMAPPED) {
  815.                         if (userpos == superpos) {
  816.  
  817.                                 if (base==0) {
  818.                                         base = userpos;
  819.                                 }
  820.                                 /* Adjacent? */
  821.                                 if (base+size == userpos) {
  822.                                         size += pagesize;
  823.                                         retry = TRUE;
  824.                                 }
  825.                         }
  826.                 }
  827.  
  828.         } while(retry);
  829.  
  830.         if (size==0L) {
  831.                 Printf("The zero page is not remapped.\n");
  832.                 err = 5;
  833.         }
  834.  
  835.          /* lower is now the lower end which is remapped.
  836.             size is the length of the remapped memory
  837.             base is the address it is remapped to */
  838.  
  839.         if (err==0L) {
  840.  
  841.          /* Make a copy of the software levels to be able to restore
  842.             them later in case of an error. */
  843.  
  844.          if (ctxl=GetMapping(ctx)) {
  845.           if (sctxl=GetMapping(sctx)) {
  846.  
  847.            /* Modify both contexts such that the zeropage is SINGLE.
  848.               This operation is very costy, but it doesn't matter
  849.               except for speed penalties if this is not un-done */
  850.  
  851.               err=ERROR_NO_FREE_STORE;
  852.               props=MAPP_SINGLEPAGE;
  853.  
  854.            if (SetProperties(ctx,props,props,lower,size,TAG_DONE)) {
  855.             if (SetProperties(sctx,props,props,lower,size,TAG_DONE)) {
  856.              if (RebuildTrees(ctx,sctx,NULL)) {
  857.  
  858.                Disable();
  859.  
  860.                /* The new property flags */
  861.                props=MAPP_SINGLEPAGE|MAPP_CACHEINHIBIT;
  862.                CacheClearU();
  863.                CopyMMULess((void *)lower,(void *)base,size);
  864.  
  865.                /* Map in the properties immediately. This should always work,
  866.                   except the parameters are invalid - which they aren't.
  867.                   This extra step is required because all other calls might
  868.                   break the Disable() above. */
  869.  
  870.                if (SetPages(ctx,props,lower,size,pagesize,0L)) {
  871.                 if (SetPages(sctx,props,lower,size,pagesize,0L)) {
  872.  
  873.                  /* Tell the contexts not to relocate the zero page even in case MuForce
  874.                     is installed later, i.e. the software emulation should read
  875.                     the data from the relocated position, not from the original. */
  876.  
  877.                  SetMMUContextData(ctx,MCXTAG_ZEROBASE,0L,TAG_DONE);
  878.                  SetMMUContextData(sctx,MCXTAG_ZEROBASE,0L,TAG_DONE);
  879.  
  880.                  /* Now make the modifications in the abstraction level. */
  881.                  if (SetProperties(ctx,props,~0L,lower,size,TAG_DONE)) {
  882.                   if (SetProperties(sctx,props,~0L,lower,size,TAG_DONE)) {
  883.  
  884.                         /* The modifications in the hardware level are actually already done.
  885.                            Calling RebuildTree isn't stricly required here, but we do it
  886.                            anyways to clear the dirty flags. This might or might not fail,
  887.                            but the resulting MMU trees are always what we want. In
  888.                            case it fails, the dirty flags are set. So what... */
  889.  
  890.                         /* We're done here. Fine. */
  891.                         err=0;
  892.                   }
  893.                  }
  894.                  /* We can't set the software level. Urgh. At least, we can
  895.                     restore it how it looked like before. */
  896.                 }
  897.                } /* of if SetPages */
  898.  
  899.                /* We try to restore the hardware tables now. */
  900.                if (err) {
  901.                 props=MAPP_REMAPPED|MAPP_SINGLEPAGE|MAPP_COPYBACK;
  902.                 SetMMUContextData(ctx,MCXTAG_ZEROBASE,base,TAG_DONE);
  903.                 SetMMUContextData(sctx,MCXTAG_ZEROBASE,base,TAG_DONE);
  904.  
  905.                 if ((!SetPages(ctx,props,lower,size,pagesize,base)) ||
  906.                     (!SetPages(sctx,props,lower,size,pagesize,base))) {
  907.                         /* We can't restore the hardware tables either! */
  908.                         Alert(0xbe000101);
  909.                         /* Sorry, go guru. We can't do much more here... */
  910.                 }
  911.                }
  912.  
  913.                Enable();
  914.              }
  915.             }
  916.            } /* of if SetProperties() */
  917.  
  918.            /* We can't build the software level. In the one way or the other,
  919.               just restore the previous software abstraction level. */
  920.  
  921.            if (err) {
  922.                 SetPropertyList(ctx,ctxl);
  923.                 SetPropertyList(sctx,sctxl);
  924.            }
  925.  
  926.            /* The software level is now restored. The
  927.               hardware level has been restored above.
  928.               Now call RebuildTree() to clear the dirty
  929.               flags.
  930.               If this fails, tough luck. Both levels are
  931.               actually fine, except for the busy flags. */
  932.  
  933.            RebuildTrees(ctx,sctx,NULL);
  934.  
  935.            ReleaseMapping(sctx,sctxl);
  936.           } /* of if made copy */
  937.           ReleaseMapping(ctx,ctxl);
  938.          } /* of if made copy */
  939.         } /* of if (err==0) */
  940.  
  941.           /* Release the locks */
  942.         UnlockMMUContext(sctx);
  943.         UnlockMMUContext(ctx);
  944.         UnlockContextList();
  945.  
  946.         return err;
  947. }
  948. ///
  949. /// ChipLowEnd
  950. ULONG ChipLowEnd(void)
  951. {
  952. ULONG low;
  953. struct MemHeader *head;
  954.  
  955.         low=0x00200000;         /* This is definitely the upper end of chip mem */
  956.  
  957.         Forbid();
  958.         for(head=(struct MemHeader *)SysBase->MemList.lh_Head;
  959.                    head->mh_Node.ln_Succ;
  960.                    head=(struct MemHeader *)(head->mh_Node.ln_Succ)) {
  961.                 if (head->mh_Attributes & MEMF_CHIP) {
  962.                         if ((ULONG)(head->mh_Lower)<low) {
  963.                                 low=(ULONG)(head->mh_Lower);
  964.                         }
  965.                 }
  966.         }
  967.         Permit();
  968.  
  969.         return low;
  970. }
  971. ///
  972. /// MoveSSP
  973. int MoveSSP(LONG stacksize)
  974. {
  975. ULONG minsize;
  976. struct Task *task;
  977. UBYTE *newstack;
  978.  
  979.         minsize=(UBYTE *)SysBase->SysStkUpper-(UBYTE *)SysBase->SysStkLower;
  980.         if (stacksize<minsize) {
  981.                 task=FindTask(NULL);
  982.                 stacksize=(UBYTE *)(task->tc_SPUpper)-(UBYTE *)(task->tc_SPLower);
  983.         }
  984.         if (stacksize<minsize)
  985.                 stacksize=minsize;
  986.  
  987.         /* Round this to two cache lines */
  988.  
  989.         stacksize += 0x1f;
  990.         stacksize &= ~0x1f;
  991.  
  992.         /* This must be fast, or this function is a joke... */
  993.         newstack=AllocMem(stacksize,MEMF_CLEAR|MEMF_PUBLIC|MEMF_FAST);
  994.  
  995.         if (newstack==NULL) {
  996.                 return ERROR_NO_FREE_STORE;
  997.         }
  998.  
  999.         SuperStackSwap(newstack,stacksize);
  1000.  
  1001.         return 0;
  1002. }
  1003. ///
  1004. /// SuperStackSwap
  1005. void SuperStackSwap(UBYTE *newstack,ULONG size)
  1006. {
  1007. UBYTE *oldsp,*newsp;
  1008. size_t oldsize;
  1009. UWORD sum;
  1010. UWORD *p;
  1011.  
  1012.         /* Yup, this is possible in C */
  1013.         Disable();
  1014.         oldsp=SuperState();
  1015.  
  1016.         /* copy the stack over to the upper limit */
  1017.         oldsize=(UBYTE *)(SysBase->SysStkUpper)-oldsp;
  1018.         if (oldsize>0 && oldsize<size) {
  1019.                 newsp=newstack+size-oldsize;
  1020.                 memcpy(newsp,oldsp,oldsize);
  1021.         } else  newsp=newstack+size;
  1022.         UserState(newsp);
  1023.  
  1024.         /* Now tell this exec! */
  1025.         SysBase->SysStkUpper=newstack+size;
  1026.         SysBase->SysStkLower=newstack;
  1027.  
  1028.         /* Recalculate the checksum */
  1029.         p=&SysBase->SoftVer;
  1030.         sum=0xffff;
  1031.         while(p<&SysBase->ChkSum)
  1032.                 sum -= *p++;
  1033.  
  1034.         SysBase->ChkSum=sum;
  1035.         Enable();
  1036.  
  1037. }
  1038. ///
  1039. /// CopyMMULess
  1040. void CopyMMULess(void *to,void *from,ULONG size)
  1041. {
  1042.         _cw_from=from;
  1043.         _cw_to=to;
  1044.         _cw_size=size;
  1045.         WithoutMMU(&__CopyWO);
  1046. }
  1047. ///
  1048. /// CopyWO
  1049. ULONG __CopyWO()
  1050. {
  1051.         memcpy(_cw_to,_cw_from,(size_t)_cw_size);
  1052.         CacheClearU();
  1053.         return 0;
  1054. }
  1055. ///
  1056.  
  1057.  
  1058.  
  1059.  
  1060.